package cn.com.ursaminor.mysql4j.core;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.ursaminor.mysql4j.util.Mysql4jUtil;

/*
 	Single-Table Syntax:
 	
	DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [[AS] tbl_alias]
	    [PARTITION (partition_name [, partition_name] ...)]
	    [WHERE where_condition]
	    [ORDER BY ...]
	    [LIMIT row_count] 
	
	---------------------------------------------------------------------
	
	Multiple-Table Syntax:
	
	DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
	    tbl_name[.*] [, tbl_name[.*]] ...
	    FROM table_references
	    [WHERE where_condition]
	
	DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
	    FROM tbl_name[.*] [, tbl_name[.*]] ...
	    USING table_references
	    [WHERE where_condition]    
 */
/**
 * 该类拼接生成delete语句，并提交.
 * 
 * @author 小熊
 * @version 1.0
 */
public class Deleter
{
    private final static Logger logger = LoggerFactory.getLogger(Deleter.class);

    // -----------------------------------------------------------------------------------------------------------------

    private Table table;

    private StringBuffer delete;
    private StringBuffer from;
    private StringBuffer where;
    private StringBuffer order;
	private StringBuffer limit;
	
	/**
	 *	构造方法.
	 *
	 *	@param table 要删除数据的表
	 */
	public Deleter(Table table)
    {
    	this.table = table;
    	delete = new StringBuffer("delete ").append(table.getAlias());
    	from = new StringBuffer(" from ").append(table.getString());
    }
    
	/**
	 *	关联表，用于关联方式删除数据.
	 *
	 *	@param abstTable 关联表
	 *  @return 当前Deleter对象
	 */
    public Deleter with(AbstTable abstTable)
	{
    	from.append(",").append(abstTable.getString());
		return this;
	}
    
    /**
	 *	关联表，用于关联方式删除数据.
	 *
	 *	@param abstTable 关联表
	 *	@param expr 布尔表达式
	 *  @return 当前Deleter对象
	 */
    public Deleter with(AbstTable abstTable, BoolExpr expr)
	{
    	with(abstTable);
		where(expr);
		return this;
	}
	
    /**
	 *	拼接where子句.
	 *
	 *	@param expr 布尔表达式
	 *  @return 当前Deleter对象
	 *  @see Query#where(BoolExpr)
	 */
	public Deleter where(BoolExpr expr)
    {
        if(expr == null || expr.getString() == null) return this;
        if(expr.getCount()>1)
        {
            if (where == null) where = new StringBuffer(" where (").append(expr.getString()).append(")");
            else where.append(" and (").append(expr.getString()).append(")");
        }
        else
        {
            if (where == null) where = new StringBuffer(" where ").append(expr.getString());
            else where.append(" and ").append(expr.getString());
        }
        return this;
    }
	
	/**
	 *	拼接order by子句.
	 *
	 *	@param o 字段数组
	 *  @return 当前Deleter对象
	 *  @see Query#order(Column...)
	 */
	public Deleter order(Column...o)
	{
		if(o==null) return this;
		for(Column oo : o)
		{
			if(oo==null) continue;
			if(order==null) order = new StringBuffer(" order by ").append(oo.getString());
			else order.append(",").append(oo.getString());
		}
		return this;
	}

	/**
	 *	拼接order by子句.
	 *
	 *	@param f 函数表达式数组
	 *  @return 当前Deleter对象
	 *  @see Query#order(FunExpr...)
	 */
	public Deleter order(FunExpr...f)
	{
		if(f==null) return this;
		for(FunExpr ff : f)
		{
			if(ff==null) continue;
			if(order==null) order = new StringBuffer(" order by ").append(ff.getString());
			else order.append(",").append(ff.getString());
		}
		return this;
	}

	/**
	 *	拼接limit子句.
	 *
	 *	@param offset 偏移量
	 *  @param count 返回结果数
	 *  @return 当前Deleter对象
	 *  @see Query#limit(Integer, Integer)
	 */
	public Deleter limit(Integer offset, Integer count)
	{
		limit = new StringBuffer(" limit ").append(offset).append(",").append(count);
		return this;
	}

	/**
	 *	拼接limit子句.
	 *
	 *  @param count 返回结果数
	 *  @return 当前Deleter对象
	 *  @see Query#limit(Integer)
	 */
	public Deleter limit(Integer count)
	{
		limit = new StringBuffer(" limit ").append(count);
		return this;
	}

	/**
	 *	获得当前sql语句.
	 *
	 *  @return sql语句 
	 */
    public String getSql()
    {
        return new StringBuffer(delete).append(from).append(where==null?"":where).append(order==null?"":order).append(limit==null?"":limit).toString();
    }

    /**
	 *	提交sql.
	 *
	 *  @return 影响行数
	 */
    public int execute()
    {
    	String sql = getSql();
        logger.info(sql);
        int r = table.getJdbcTemplate().update(getSql());
        return r;
    }

	public String toString()
    {
    	return getSql();
    }

    // --静态快捷方法-----------------------------------------------------------------------------------------------------

	/**
	 *	获得删除pojo对象的sql语句.
	 *
	 *	@param table 表
	 *	@param pojo pojo对象，也可为Row对象
	 *  @return sql语句 
	 */
    public static String getSql(Table table, Object pojo)
    {
        try
        {
        	Column pk = table.primaryKey;
        	Object obj = null;
        	
        	if(pojo instanceof Map)
        	{
        		obj = ((Map)pojo).get(pk.getAliasOrName());
        		if(obj==null) throw new Exception("The value of primaryKey " + pk.getAliasOrName() + " is null!");
        	}
        	else
        	{
        		Method method = pk.method;
                if(method==null) throw new Exception("The getter method of primaryKey is not exist!");
                obj = method.invoke(pojo, new Object[0]);
                if(obj==null) throw new Exception("The value of primaryKey " + method.getName() + "() returned null!");
        	}
            
            String value = null;
            if (pk instanceof Num) value = obj.toString();
            else if (pk instanceof Chr) value = "'" + obj + "'";
            else if (pk instanceof Datetime) value = "'" + Mysql4jUtil.formatDate((Date) obj) + "'";

            return new StringBuffer("delete from ").append(table.getName()).append(" where ").append(pk.name).append("=").append(value).toString();
        }
        catch(Exception e)
        {
            logger.error(e.toString());
            return null;
        }
    }

    /**
	 *	把pojo数据从table表中删除.
	 *
	 *	@param table 表
	 *  @param pojo 数据对象
	 *  @return 影响行数
	 */
    public static int delete(Table table, Object pojo)
    {
        String sql = getSql(table, pojo);
        logger.info(sql);
        return table.getJdbcTemplate().update(sql);
    }

    /**
	 *	把pojo数据列表从table表中删除.
	 *
	 *	@param table 表
	 *  @param pojos 数据对象列表
	 *  @return 影响行数
	 */
    public static int delete(Table table, List pojos)
    {
    	if(pojos==null || pojos.size()==0) return 0;
    	
    	int result = 0;
		for(Object pojo : pojos)
		{
			result += delete(table, pojo);
		}
		return result;
    }
}
